﻿//PlazaMetadataHelper.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Plaza.Metadata
{
	using System;
	using System.Collections.Generic;
	using System.Linq;

	using Ecng.Collections;
	using Ecng.Common;

	static class PlazaMetadataHelper
	{
		public static IEnumerable<PlazaTable> GetAllTables()
		{
			var type = typeof(PlazaTableRegistry);

			return type
				.GetFields()
				.Where(x => x.FieldType == typeof(PlazaTable))
				.Select(fieldInfo => (PlazaTable)fieldInfo.GetValue(type));
		}

		public static IEnumerable<PlazaColumn> GetAllColumns(this PlazaColumns columns)
		{
			// В поток (stream) Плазы первыми нужно передавать эти три служебные колонки, 
			// иначе будут ошибки при подключении к потокам репликации
			// При стандартной переборке через Reflection они попадут в список последними, потому что объявлены в родительском классе.
			var result = new List<PlazaColumn>
			{
				columns.ReplId,
				columns.ReplRev,
				columns.ReplAct
			};

			foreach (var fieldInfo in columns.GetType().GetFields().Where(x => x.FieldType == typeof(PlazaColumn)))
			{
				if (!(fieldInfo.Name == "ReplId" || fieldInfo.Name == "ReplRev" || fieldInfo.Name == "ReplAct"))
				{
					var plazaColumn = (PlazaColumn)fieldInfo.GetValue(columns);
					System.Diagnostics.Debug.Assert(plazaColumn != null, "Field {0} is null".Put(fieldInfo.Name));
					result.Add(plazaColumn);
				}
			}

			return result;
		}

		/// <summary>
		/// Добавляет только обязательные колонки (IsMandatory == true)
		/// </summary>
		public static void AddAllMandatoryColumns(this PlazaTable table)
		{
			if (table == null)
				throw new ArgumentNullException("table");

			table.Columns.AddRange(table.GetMetadata().GetAllColumns().Where(x => x.IsMandatory));
		}

		//public static IEnumerable<PlazaColumn> GetAllMandatoryColumns(this PlazaColumns columns)
		//{
		//    return GetAllColumns(columns).Where(x => x.IsMandatory);
		//}

		public static PlazaColumns GetMetadata(this PlazaTable table)
		{
			if (table == null)
				throw new ArgumentNullException("table");

			var metadata = GetAllMetadata().FirstOrDefault(x => x.Table.Equals(table));

			if (metadata == null)
				throw new ArgumentException("Для таблицы {0} отсутствуют метаданные в классе PlazaColumnRegistry.".Put(table.UniqueName));

			return metadata;
		}

		//internal static PlazaColumns GetMetadata(string replicationStream, ReplicationScheme replicationScheme, string tableName)
		//{
		//    if (tableName.IsEmpty())
		//        throw new ArgumentNullException("tableName");

		//    return GetAllMetadata().FirstOrDefault(
		//        x => x.Table.ReplicationStream == replicationStream
		//            && x.Table.ReplicationScheme == replicationScheme
		//            && x.Table.Name == tableName);
		//}

		public static IEnumerable<PlazaColumns> GetAllMetadata()
		{
			var type = typeof(PlazaColumnRegistry);

			return type
				.GetFields()
				.Where(x => GetRootType(x.FieldType) == typeof(PlazaColumns))
				.Select(fieldInfo => (PlazaColumns)fieldInfo.GetValue(type));
		}

		// Может быть, это нужно вынести в отдельный класс, как extension method
		private static Type GetRootType(Type child)
		{
			Type result = child;

			while (result.BaseType != null && result.BaseType != typeof(object))
			{
				result = result.BaseType;
			}

			return result;
		}
	}
}